package com.vca.service.service.Impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.vca.common.constants.Constants;
import com.vca.common.constants.SysConfigConstants;
import com.vca.common.exception.VcaException;
import com.vca.common.model.category.Category;
import com.vca.common.model.course.Course;
import com.vca.common.model.course.CourseScheduling;
import com.vca.common.model.export.CourseSchedulingExport;
import com.vca.common.model.order.StoreOrder;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.system.SystemGroupData;
import com.vca.common.model.user.User;
import com.vca.common.page.CommonPage;
import com.vca.common.request.*;
import com.vca.common.response.AdminHeaderResponse;
import com.vca.common.response.CourseSchedulingAdminByIdResponse;
import com.vca.common.response.CourseSchedulingAdminResponse;
import com.vca.common.utils.DateUtil;
import com.vca.common.utils.PageUtils;
import com.vca.common.utils.VcaUtil;
import com.vca.common.vo.ExcelCourseOrderInfo;
import com.vca.common.vo.ExcelCourseSchedulingById;
import com.vca.common.vo.dateLimitUtilVo;
import com.vca.service.dao.course.CourseDao;
import com.vca.service.dao.course.CourseSchedulingDao;
import com.vca.service.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程排课表 服务实现类
 * </p>
 *
 * @author chenBing
 * @since 2022-09-19
 */
@Service
@Slf4j
public class CourseSchedulingServiceImpl extends ServiceImpl<CourseSchedulingDao, CourseScheduling> implements CourseSchedulingService {

    @Autowired
    private CourseSchedulingDao dao;

    @Autowired
    private CourseDao courseDao;

    @Autowired
    private CourseService courseService;

    @Autowired
    private SystemGroupDataService systemGroupDataService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private VcaLineUpService vcaLineUpService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private StoreOrderService orderService;

    @Autowired
    private StoreOrderInfoService orderInfoService;

    @Autowired
    private ExportService exportService;

    @Autowired
    private UserService userService;

    /**
     * 课程排课列表
     *
     * @param request
     * @param pageParamRequest
     * @return
     * @author Li
     * @date 2022/11/14 15:34
     */
    @Override
    public PageInfo getAdminList(SchedulingAdminListRequest request, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getIsDel, false);
        if (ObjectUtil.isNotEmpty(request.getKeywords())) {
            List<Integer> ids = courseDao.fuzzySearch(request.getKeywords());
            if (ObjectUtil.isEmpty(ids)) {
                List<CourseSchedulingAdminResponse> courseSchedulingAdminResponses = new ArrayList<>();
                return PageUtils.startPage(courseSchedulingAdminResponses, pageParamRequest.getPage(), pageParamRequest.getLimit());
            }
            wrapper.in(CourseScheduling::getCourseId, ids);
        }
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            if (request.getSchedulingStatus().equals(3)) {
                wrapper.eq(CourseScheduling::getIsCancel, 1);
            }
        }
        if (ObjectUtil.isNotEmpty(request.getDateLimit())) {
            getRequestTimeWhere(wrapper, request);
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            wrapper.eq(CourseScheduling::getStatus, request.getStatus());
        }

        wrapper.orderByDesc(CourseScheduling::getCourseId);
        List<CourseScheduling> courseSchedulings = dao.selectList(wrapper);
        List<CourseSchedulingAdminResponse> adminList = new ArrayList<>();
        Map<String, List<HashMap<String, Object>>> courseAdminConfig = systemGroupDataService.getCourseAdminConfig();
        List<HashMap<String, Object>> price = courseAdminConfig.get("priceList");
        List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
        HashMap<String, String> info = systemConfigService.info(SysConfigConstants.CONFIG_FROM_ID_BASIC);

        if (ObjectUtil.isNotEmpty(courseSchedulings)) {
            LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
            courseWrapper.in(Course::getId, courseSchedulings.stream().map(CourseScheduling::getCourseId).collect(Collectors.toList()));
            //查询课程
            List<Course> courses = courseDao.selectList(courseWrapper);
            courseSchedulings.forEach(e -> {
                CourseSchedulingAdminResponse response = new CourseSchedulingAdminResponse();
                BeanUtils.copyProperties(e, response);
                if (ObjectUtil.isEmpty(e.getIsCancel())) {
                    response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                } else {
                    if (e.getIsCancel().equals(1)) {
                        response.setSchedulingStatus(3);
                    } else {
                        response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                    }
                }
                price.forEach(p -> {
                    Map map = JSON.parseObject(JSONObject.toJSONString(p), Map.class);
                    if (map.get("id").equals(e.getPriceId())) {
                        response.setPrice(map.get("coursePrice").toString());
                    }
                });
                languageList.forEach(language -> {
                    Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                    if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                        response.setCourseLanguage(languageMap.get("courseLanguage").toString());
                    }
                });
                //课程信息拷贝
                courses.forEach(course -> {
                    if (e.getCourseId().equals(course.getId())) {
                        Category category = categoryService.getOne(new LambdaQueryWrapper<Category>().eq(Category::getId, course.getCourseTypeId()));
                        response.setLabelColor(category.getLabelColor());
                        response.setName(course.getName());
                        response.setCover(course.getCover());
                        response.setCoverImage(course.getCover());
                    }
                });
                response.setStatus(e.getStatus() ? 1 : 0);
                adminList.add(response);
            });
        }
        List<CourseSchedulingAdminResponse> responses = adminList;
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            responses = adminList.stream().filter(e -> e.getSchedulingStatus().equals(Integer.valueOf(request.getSchedulingStatus()))).collect(Collectors.toList());
        }
        responses.sort(Comparator.comparing(CourseSchedulingAdminResponse::getSchedulingDate));
        return PageUtils.startPage(responses, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    @Override
    public ExcelCourseSchedulingById getBookingDetail(String id, PageParamRequest pageParamRequest) {
        /**
         * 查找排期数据
         */
        CourseScheduling courseScheduling = getById(id);
        if(courseScheduling == null) {
            throw new VcaException("不存在这个课程排期");
        }
        Course course = courseService.getById(courseScheduling.getCourseId());
        if(course == null) {
            throw new VcaException("不存在这个课程");
        }
        String name = course.getName(); //课程名称
        SystemGroupData systemGroupData1 = systemGroupDataService.getById(courseScheduling.getCourseLanguageId());
        if(systemGroupData1 == null) {
            throw new VcaException("不存在这个课程语言");
        }
        Gson gson = new Gson();
        JsonObject value1 = gson.fromJson(systemGroupData1.getValue(), JsonObject.class);
        String value11 = value1.get("fields").getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString(); //排课语言
        SystemGroupData systemGroupData2 = systemGroupDataService.getById(courseScheduling.getPriceId());
        if(systemGroupData2 == null) {
            throw new VcaException("不存在这个课程价格");
        }
        JsonObject value2 = gson.fromJson(systemGroupData2.getValue(), JsonObject.class);
        String asString = value2.get("fields").getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString();
        BigDecimal value22 = new BigDecimal(asString); //排课价格
        //标题数据
        ExcelCourseSchedulingById excelCourseById = new ExcelCourseSchedulingById();
        BeanUtils.copyProperties(courseScheduling, excelCourseById);
        boolean status = exportService.checkExcelStatus(courseScheduling.getSchedulingDate(), courseScheduling.getSchedulingStartTime(), courseScheduling.getSchedulingEndTime());
        excelCourseById.setStatus(status?"已结束":"未开始");
        excelCourseById.setName(name);
        excelCourseById.setCourseLanguage(value11);
        excelCourseById.setPrice(value22);
        excelCourseById.setAllStudentsNumber(excelCourseById.getExternalStudentsNumber()+excelCourseById.getInternalStudentsNumber());
        /**
         * 查找核销或待核销的数据
         */
        List<ExcelCourseOrderInfo> list = new ArrayList();
//        excelCourseById.setList(list);
        LambdaQueryWrapper<StoreOrderInfo> storeOrderInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getSchedulingId, id);
        //已核销 和 待支付
        LambdaQueryWrapper<StoreOrder> storeOrderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        storeOrderLambdaQueryWrapper.and(wrapper -> wrapper.in(StoreOrder::getStatus, Arrays.asList(2, 3)).in(StoreOrder::getType, Arrays.asList(0,1,2,3)).or(wrapper1 -> wrapper1.eq(StoreOrder::getPaid, false).eq(StoreOrder::getStatus, 0)));
        storeOrderLambdaQueryWrapper.eq(StoreOrder::getIsDel, false);
        List<StoreOrder> storeOrderList = orderService.list(storeOrderLambdaQueryWrapper);
        //已核销和 待支付主订单
        List<String> storeOrderNoList = null;
        if(CollectionUtil.isNotEmpty(storeOrderList)) {
            storeOrderNoList = storeOrderList.stream().map(StoreOrder::getOrderId).collect(Collectors.toList());
        }
        //待核销
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getStatus, 1);
//        storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getRefundStatus, 0);
        //待支付
//        storeOrderLambdaQueryWrapper.eq(StoreOrder::getPaid, false);
//        storeOrderLambdaQueryWrapper.eq(StoreOrder::getStatus, 0);
        final List<String> finalStoreOrderNoList = storeOrderNoList;
        if(CollectionUtil.isNotEmpty(finalStoreOrderNoList)) {
            storeOrderInfoLambdaQueryWrapper.and(wrapper->wrapper.eq(StoreOrderInfo::getStatus, 1).eq(StoreOrderInfo::getRefundStatus, 0).or().in(CollectionUtil.isNotEmpty(finalStoreOrderNoList), StoreOrderInfo::getOrderNo, finalStoreOrderNoList));
        }else {
            storeOrderInfoLambdaQueryWrapper.eq(StoreOrderInfo::getStatus, 1).eq(StoreOrderInfo::getRefundStatus, 0);
        }
        List<StoreOrderInfo> storeOrderInfos = orderInfoService.list(storeOrderInfoLambdaQueryWrapper);
        if(CollectionUtil.isNotEmpty(storeOrderInfos)) {
            for (int i = 0; i < storeOrderInfos.size(); i++) {
                StoreOrderInfo storeOrderInfo = storeOrderInfos.get(i);
                ExcelCourseOrderInfo excelCourseOrderInfo = new ExcelCourseOrderInfo();
                BeanUtils.copyProperties(storeOrderInfo, excelCourseOrderInfo);
                //购买人
                User buyer = userService.getById(storeOrderInfo.getBuyer());
                if(buyer != null) {
                    excelCourseOrderInfo.setNickname(buyer.getNickname());
                    excelCourseOrderInfo.setPhone(VcaUtil.maskMobile(buyer.getPhone()));
                    excelCourseOrderInfo.setEmail(buyer.getEmail());
                }else {
//                    throw new VcaException("不存在该购买人："+storeOrderInfo.getBuyer());
                }
                //主订单
                StoreOrder storeOrder = orderService.getByOrderId(storeOrderInfo.getOrderNo());
                if(storeOrder != null) {
                    //支付渠道
                    if (storeOrder.getUserType() == 1) {
                        excelCourseOrderInfo.setChannel("后台赠送");
                    } else {
                        excelCourseOrderInfo.setChannel("微信支付");
                    }
                    //主订单uid
                    if(StringUtils.isBlank(excelCourseOrderInfo.getNickname()) && storeOrder.getUid() != null) {
                        User user = userService.getById(storeOrder.getUid());
                        if(user != null) {
                            excelCourseOrderInfo.setNickname(user.getNickname());
                            excelCourseOrderInfo.setPhone(VcaUtil.maskMobile(user.getPhone()));
                            excelCourseOrderInfo.setEmail(user.getEmail());
                        }
                    }
                }else {
//                    throw new VcaException("不存在该主订单："+storeOrderInfo.getOrderNo());
                }
                //核销状态
                if(storeOrder != null) {
                    if(storeOrder.getPaid()) {
                        if(storeOrderInfo.getWriteOffClerkId() == null) {
                            excelCourseOrderInfo.setWriteOffStatus("待核销");
                        }else {
                            excelCourseOrderInfo.setWriteOffStatus("已核销");
                        }
                    }else {
                        excelCourseOrderInfo.setWriteOffStatus("待支付");
                    }
                }
                //核销时间
                if(storeOrderInfo.getWriteOffTime() != null) {
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm");
                    excelCourseOrderInfo.setWriteOffTime(simpleDateFormat.format(storeOrderInfo.getWriteOffTime()));
                }
                list.add(excelCourseOrderInfo);
            }
        }
        excelCourseById.setPageInfo(CommonPage.restPage(PageUtils.startPage(list, pageParamRequest.getPage(), pageParamRequest.getLimit())));

        return excelCourseById;
    }

    /**
     * 添加课程排课
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/17   10:50
     */
    @Override
    public boolean addScheduling(SchedulingAddRequest<CourseSchedulingAdminRequest> request) {
        Course course = courseDao.selectOne(new LambdaQueryWrapper<Course>().eq(Course::getId, request.getSchedulingRequests().get(0).getCourseId()).eq(Course::getIsDeleted, 0));
        if (ObjectUtil.isEmpty(course)) {
            throw new VcaException("该课程不存在");
        }
        List<CourseScheduling> courseSchedulings = new ArrayList();
        request.getSchedulingRequests().forEach(e -> {
            CourseScheduling courseScheduling = new CourseScheduling();
            BeanUtils.copyProperties(e, courseScheduling);
            List<String> schedulingTime = VcaUtil.stringToArrayStrRegex(e.getSchedulingTime(), "~");
            courseScheduling.setSchedulingStartTime(schedulingTime.get(0));
            courseScheduling.setSchedulingEndTime(schedulingTime.get(1));
            courseScheduling.setStatus(true);
            courseScheduling.setIsCancel(0);
            courseSchedulings.add(courseScheduling);
        });
        Boolean sendNotice;
        if (checkSchedulingQuta(course.getId())) {
            sendNotice = true;
        } else {
            sendNotice = false;
        }
        return transactionTemplate.execute(e -> {
            Integer a = 0;
            for (CourseScheduling scheduling : courseSchedulings) {
                dao.insert(scheduling);
                if (checkSchedulingDate(scheduling)) {
                    a++;
                }
            }
            if (a > 0 && sendNotice) {
                vcaLineUpService.noticeByMainId(course.getId(), Constants.ORDER_TYPE_COURSE);
            }
            return Boolean.TRUE;
        });
    }

    /**
     * 修改课程排课
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/17   10:50
     */
    @Override
    public boolean updateScheduling(CourseSchedulingAdminRequest request) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getId, request.getId());
        CourseScheduling courseScheduling = dao.selectOne(wrapper);
        int sum=0;
        if (ObjectUtil.isEmpty(courseScheduling)) {
            throw new VcaException("当前排课不存在");
        }
        if (ObjectUtil.isNotEmpty(request.getCourseLanguageId())) {
            courseScheduling.setCourseLanguageId(request.getCourseLanguageId());
        }
        if (ObjectUtil.isNotEmpty(request.getInternalLimit())) {
            courseScheduling.setInternalLimit(request.getInternalLimit());
            sum+=request.getInternalLimit();
        }else {
            sum+=courseScheduling.getInternalLimit();
        }
        if (ObjectUtil.isNotEmpty(request.getExternalLimit())) {
            if (request.getExternalLimit() > courseScheduling.getExternalLimit() && checkSchedulingQuta(courseScheduling.getCourseId()) && checkSchedulingDate(courseScheduling)) {
                vcaLineUpService.noticeByMainId(courseScheduling.getCourseId(), Constants.ORDER_TYPE_COURSE);
            }
            courseScheduling.setExternalLimit(request.getExternalLimit());
            sum+=request.getExternalLimit();
        }else {
            sum+=courseScheduling.getExternalLimit();
        }
        sum+=courseScheduling.getExternalAppointment();
        sum+=courseScheduling.getInternalAppointment();
        if (ObjectUtil.isNotEmpty(request.getSeatCount())) {
            courseScheduling.setSeatCount(request.getSeatCount());
        }
        if ( courseScheduling.getSeatCount()!=sum){
            throw new VcaException("席位应等于限量与预约总和，请刷新后重新修改");
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            courseScheduling.setStatus(request.getStatus());
        }
        return transactionTemplate.execute(e -> {
            dao.updateById(courseScheduling);
            return Boolean.TRUE;
        });
    }

    /**
     * 课程排课列日历列表
     *
     * @param request
     * @return
     * @author Li
     * @date 2022/11/18 14:46
     */
    @Override
    public List<CourseSchedulingAdminResponse> getCalendarList(SchedulingAdminListRequest request) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        if (ObjectUtil.isNotEmpty(request.getKeywords())) {
            wrapper.in(CourseScheduling::getCourseId, courseDao.fuzzySearch(request.getKeywords()));
        }
        if (ObjectUtil.isNotEmpty(request.getStatus())) {
            wrapper.eq(CourseScheduling::getStatus, request.getStatus());
        }
//        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
//            wrapper.eq(CourseScheduling::getSchedulingStatus, request.getSchedulingStatus());
//        }
        List<CourseScheduling> courseSchedulings = dao.selectList(wrapper);
        if (ObjectUtil.isNotEmpty(request.getSchedulingStatus())) {
            List<CourseScheduling> schedulingResult = new ArrayList<>();
            courseSchedulings.forEach(scheduling -> {
                if (DateUtil.getSchedulingStatus(scheduling.getSchedulingDate(), scheduling.getSchedulingStartTime(), scheduling.getSchedulingEndTime()).equals(Integer.valueOf(request.getSchedulingStatus()))) {
                    schedulingResult.add(scheduling);
                }
            });
            courseSchedulings.retainAll(schedulingResult);
        }
        List<CourseSchedulingAdminResponse> adminList = new ArrayList<>();
        String nowDate = DateUtil.nowDate("yyyy-MM-dd HH:mm:ss");
        if (ObjectUtil.isNotEmpty(courseSchedulings)) {
            LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
            courseWrapper.in(Course::getId, courseSchedulings.stream().map(CourseScheduling::getCourseId).collect(Collectors.toList()));
            List<Course> courses = courseDao.selectList(courseWrapper);
            List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
            courseSchedulings.forEach(e -> {
                CourseSchedulingAdminResponse response = new CourseSchedulingAdminResponse();
                BeanUtils.copyProperties(e, response);
                response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
                languageList.forEach(language -> {
                    Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                    if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                        response.setCourseLanguage(languageMap.get("courseLanguage").toString());
                    }
                    courses.forEach(course -> {
                        if (e.getCourseId().equals(course.getId())) {
                            Category category = categoryService.getOne(new LambdaQueryWrapper<Category>().eq(Category::getId, course.getCourseTypeId()));
                            response.setLabelColor(category.getLabelColor());
                            response.setName(course.getName());
                            response.setCover(course.getCover());
                            response.setCoverImage(course.getCover());
                        }
                    });
                });
                adminList.add(response);
            });
        }
        return adminList;
    }

    /**
     * 跟据课程id查询排期
     *
     * @param courseId
     * @return
     * @author Li
     * @date 2022/11/21 09:47
     */
    @Override
    public CourseSchedulingAdminByIdResponse getAdminScheduling(Long courseId) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getId, courseId);
        wrapper.eq(CourseScheduling::getIsDel, 0);
        CourseScheduling courseScheduling = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(courseScheduling)) {
            throw new VcaException("该排期不存在");
        }
        HashMap<String, String> info = systemConfigService.info(SysConfigConstants.CONFIG_FROM_ID_BASIC);
        List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
        Course course = courseDao.selectOne(new LambdaQueryWrapper<Course>().eq(Course::getId, courseScheduling.getCourseId()));

        languageList.forEach(language -> {
            Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
            if (languageMap.get("id").equals(courseScheduling.getCourseLanguageId())) {
                courseScheduling.setCourseLanguageName(languageMap.get("courseLanguage").toString());
            }
        });

        CourseSchedulingAdminByIdResponse response = new CourseSchedulingAdminByIdResponse();
        BeanUtils.copyProperties(courseScheduling, response);
        if (ObjectUtil.isEmpty(courseScheduling.getIsCancel())) {
            response.setSchedulingStatus(DateUtil.getSchedulingStatus(courseScheduling.getSchedulingDate(), courseScheduling.getSchedulingStartTime(), courseScheduling.getSchedulingEndTime()));
        } else {
            if (courseScheduling.getIsCancel().equals(1)) {
                response.setSchedulingStatus(3);
            } else {
                response.setSchedulingStatus(DateUtil.getSchedulingStatus(courseScheduling.getSchedulingDate(), courseScheduling.getSchedulingStartTime(), courseScheduling.getSchedulingEndTime()));
            }
        }
        response.setRatio(Double.valueOf(info.get("limit_ration")));
        if (ObjectUtil.isNotEmpty(course)) {
            response.setName(course.getName());
        }

        return response;
    }

    /**
     * 跟据课程排期id删除排期
     *
     * @param schedulingId
     * @return
     * @author Li
     * @since 2022/11/21 14:37
     */
    @Override
    public boolean deleteScheduling(Long schedulingId) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getId, schedulingId);
        wrapper.eq(CourseScheduling::getIsDel, 0);
        CourseScheduling courseScheduling = dao.selectOne(wrapper);
        if (ObjectUtil.isEmpty(courseScheduling)) {
            throw new VcaException("该排期已被删除");
        }
        courseScheduling.setStatus(false);
        courseScheduling.setIsDel(true);
        return transactionTemplate.execute(e -> {
            dao.update(courseScheduling, new LambdaUpdateWrapper<CourseScheduling>().eq(CourseScheduling::getId, schedulingId).set(CourseScheduling::getIsDel, 1));
            return Boolean.TRUE;
        });
    }

    /**
     * 跟据课程id查询排期
     *
     * @param courseId
     * @param pageParamRequest
     * @return
     * @author Li
     * @date 2022/11/21 09:47
     */
    @Override
    public PageInfo<CourseSchedulingAdminByIdResponse> getListByCourse(Long courseId, PageParamRequest pageParamRequest) {
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getCourseId, courseId);
        wrapper.eq(CourseScheduling::getIsDel, 0);
        wrapper.eq(CourseScheduling::getStatus, 1);
        wrapper.eq(CourseScheduling::getIsCancel, 0);
        wrapper.gt(CourseScheduling::getInternalLimit, 0);
        List<CourseScheduling> courseSchedulingList = dao.selectList(wrapper);
        List<CourseSchedulingAdminByIdResponse> admin = new ArrayList();
        if (ObjectUtil.isEmpty(courseSchedulingList)) {
            PageUtils.startPage(admin, pageParamRequest.getPage(), pageParamRequest.getLimit());
        }

        Map<String, List<HashMap<String, Object>>> courseAdminConfig = systemGroupDataService.getCourseAdminConfig();
        List<HashMap<String, Object>> price = courseAdminConfig.get("priceList");
        List languageList = systemGroupDataService.getCourseSchedulingAdminConfig().get("languageList");
        List<CourseSchedulingAdminByIdResponse> responses = new ArrayList<>();
        courseSchedulingList.forEach(e -> {
            languageList.forEach(language -> {
                Map languageMap = JSON.parseObject(JSONObject.toJSONString(language), Map.class);
                if (languageMap.get("id").equals(e.getCourseLanguageId())) {
                    e.setCourseLanguageName(languageMap.get("courseLanguage").toString());
                }
            });
            CourseSchedulingAdminByIdResponse response = new CourseSchedulingAdminByIdResponse();
            BeanUtils.copyProperties(e, response);
            response.setSchedulingStatus(DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime()));
            price.forEach(p -> {
                Map map = JSON.parseObject(JSONObject.toJSONString(p), Map.class);
                if (map.get("id").equals(e.getPriceId())) {
                    response.setPrice(new BigDecimal(map.get("coursePrice").toString()));
                }
            });
            //过滤出未开始的
            if (response.getSchedulingStatus() == 2) {
                responses.add(response);
            }
        });
        admin = responses.stream().sorted(Comparator.comparing(CourseSchedulingAdminByIdResponse::getInternalLimit).reversed()).collect(Collectors.toList());
        admin.sort(Comparator.comparing(CourseSchedulingAdminByIdResponse::getSchedulingDate));
        return PageUtils.startPage(admin, pageParamRequest.getPage(), pageParamRequest.getLimit());
    }

    /**
     * @return
     * @author Li
     * @date 2022/11/24
     */
    @Override
    public List<AdminHeaderResponse> getHeader(String dateLimit) {
        //初始化map
        Map<Integer, Integer> status = new HashMap();
        status.put(0, 0);
        status.put(1, 0);
        status.put(2, 0);
        status.put(3, 0);
        List<AdminHeaderResponse> responses = new ArrayList<>();
        LambdaQueryWrapper<CourseScheduling> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseScheduling::getIsDel, 0);
        if (ObjectUtil.isNotEmpty(dateLimit)) {
            getRequestTimeWhere(wrapper, new SchedulingAdminListRequest().setDateLimit(dateLimit));
        }
        List<CourseScheduling> courseSchedulings = dao.selectList(wrapper);
        String nowDate = DateUtil.nowDate("yyyy-MM-dd HH:mm:ss");
        courseSchedulings.forEach(e -> {
            Integer integer = 0;
            if (ObjectUtil.isEmpty(e.getIsCancel())) {
                //动态添加排课状态
                integer = DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime());
            } else {
                if (e.getIsCancel().equals(1)) {
                    integer = 3;
                } else {
                    //动态添加排课状态
                    integer = DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime());
                }
            }

            status.put(integer, status.get(integer) + 1);
        });

        responses.add(new AdminHeaderResponse(courseSchedulings.size(), "全部", null, 4));
        responses.add(new AdminHeaderResponse(status.get(0), "已结束", null, 0));
        responses.add(new AdminHeaderResponse(status.get(1), "进行中", null, 1));
        responses.add(new AdminHeaderResponse(status.get(2), "未开始", null, 2));
        responses.add(new AdminHeaderResponse(status.get(3), "已取消", null, 3));
        return responses;
    }

    /**
     * 上架课程排期预约状态
     *
     * @param courseSchedulingId 课程排期id
     * @return
     * @author Li
     * @date 2022/11/18 15:16
     */
    @Override
    public boolean onShell(Long courseSchedulingId) {
        CourseScheduling courseScheduling = checkScheduling(courseSchedulingId);
        courseScheduling.setStatus(true);
        return transactionTemplate.execute(e -> {
            dao.update(courseScheduling, new LambdaUpdateWrapper<CourseScheduling>().eq(CourseScheduling::getId, courseSchedulingId).set(CourseScheduling::getStatus, 1));
            return Boolean.TRUE;
        });
    }

    /**
     * 下架课程排期预约状态
     *
     * @param courseSchedulingId 课程排期id
     * @return
     * @author Li
     * @date 2022/11/18 15:16
     */
    @Override
    public boolean offShell(Long courseSchedulingId) {
        CourseScheduling courseScheduling = checkScheduling(courseSchedulingId);
        courseScheduling.setStatus(false);
        return transactionTemplate.execute(e -> {
            dao.update(courseScheduling, new LambdaUpdateWrapper<CourseScheduling>().eq(CourseScheduling::getId, courseSchedulingId).set(CourseScheduling::getStatus, 0));
            return Boolean.TRUE;
        });
    }

    /**
     * @Description:判断课程当前排期似乎否已经过了停止预约的时间
     * @author:chenbing
     * @date 2023/9/19 13:29
     */
    @Override
    public boolean checkSchedulingDate(CourseScheduling courseScheduling) {
        if (courseScheduling == null) {
            return false;
        }
        //TODO：获取课程提前停止预约时间
        Integer courseEndOrderTimeHour = Integer.valueOf(systemConfigService.getValueByKey(Constants.COURSE_END_ORDER_TIME));
        Date schedulingDate = com.vca.common.utils.DateUtil.strToDate(courseScheduling.getSchedulingDate() + " " + courseScheduling.getSchedulingStartTime() + ":00", "yyyy-MM-dd HH:mm:ss");
        DateTime offset = cn.hutool.core.date.DateUtil.offset(schedulingDate, DateField.HOUR, -courseEndOrderTimeHour);
        long between = cn.hutool.core.date.DateUtil.between(offset, cn.hutool.core.date.DateUtil.date(), DateUnit.SECOND, false);
        if (between >= 0) {
            return false;
        }
        return true;
    }

    private CourseScheduling checkScheduling(Long courseSchedulingId) {
        CourseScheduling courseScheduling = dao.selectById(courseSchedulingId);
        if (ObjectUtil.isEmpty(courseScheduling)) {
            throw new VcaException("课程不存在");
        }
        return courseScheduling;
    }

    /**
     * @Description:判断课程排期是否还有空余席位
     * @author:chenbing
     * @date 2023/9/18 16:55
     */
    @Override
    public boolean checkSchedulingQuta(Long mainId) {
        List<CourseScheduling> schedulings = list(new LambdaQueryWrapper<CourseScheduling>()
                .eq(CourseScheduling::getCourseId, mainId)
                .eq(CourseScheduling::getIsDel, false)
                .eq(CourseScheduling::getIsCancel,0)
                .gt(CourseScheduling::getSchedulingDate,DateUtil.dateToStr(new Date(),Constants.DATE_FORMAT_DATE))
                .gt(CourseScheduling::getSchedulingEndTime,DateUtil.dateToStr(new Date(),"HH:mm")));
        if (schedulings.size() <= 0) {
            return true;
        }
//        DateUtil.getSchedulingStatus(e.getSchedulingDate(), e.getSchedulingStartTime(), e.getSchedulingEndTime())
        int externalLimitTotal = schedulings.stream().mapToInt(CourseScheduling::getExternalLimit).sum();
        if (externalLimitTotal <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取request的where条件
     *
     * @param queryWrapper QueryWrapper<StoreOrder> 表达式
     * @param request      StoreOrderSearchRequest 请求参数
     */
    private void getRequestTimeWhere(LambdaQueryWrapper<CourseScheduling> queryWrapper, SchedulingAdminListRequest request) {
        if (StringUtils.isNotBlank(request.getDateLimit())) {
            dateLimitUtilVo dateLimitUtilVo = DateUtil.getDateLimit(request.getDateLimit());
            queryWrapper.between(CourseScheduling::getSchedulingDate, dateLimitUtilVo.getStartTime().substring(0, 10), dateLimitUtilVo.getEndTime().substring(0, 10));
        }
    }

    /**
     * @Description:根据课程截止时间来修改课程当前状态
     * @author:chenbing
     * @date 2022/11/28 16:09
     */
    @Override
    public boolean changeAllSchedulingStatus() {
        return false;
    }

    /**
     * @param request
     * @return boolean
     * @description 取消课程排期
     * @methodName cancel
     * @author Li
     * @date 2022/12/28 16:17
     */
    @Override
    public boolean cancel(SchedulingCancelRequest request) {
        CourseScheduling courseScheduling = checkScheduling(request.getSchedulingId());
        courseScheduling.setIsCancel(1);
        courseScheduling.setCancellationReasons(request.getReason());
        return transactionTemplate.execute(e -> {
            orderService.cancelActivity(request.getSchedulingId().intValue(), 0);
            dao.updateById(courseScheduling);
            return Boolean.TRUE;
        });
    }

    @Override
    public List<CourseSchedulingExport> getCourserSchedulingExports(String startTime, String endTime) {
        return dao.getCourseSchedulingExport(startTime, endTime);
    }
}
